﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using GrayParrot.Web.Security;
using GrayParrot.Configuration;
using GrayParrot.Web.Security.Configuration;

namespace GrayParrot.Web.Controls
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:MenuBuilder runat=server></{0}:MenuBuilder>")]
    public class MenuBuilder : WebControl
    {
        public string SiteMapDataSourceID { get; set; }
        public bool IncludeRoot { get; set; }
        public bool AssignRoles { get; set; }
        public string[] m_userRoles = null;
        private IPrincipal m_currentUser = null;
        private bool m_securityEnabled = false;

        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public bool SecurityEnabled
        {
            get { return m_securityEnabled; }
            set { m_securityEnabled = value; }
        }

        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public IPrincipal CurrentUser
        {
            get 
            {
                if (m_currentUser == null)
                {
                    // if null, try with the standard current user...
                    m_currentUser = HttpContext.Current.User;
                }

                return m_currentUser; 
            }
            set { m_currentUser = value; }
        }

        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? String.Empty : s);
            }

            set
            {
                ViewState["Text"] = value;
            }
        }

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }


        protected override void Render(HtmlTextWriter writer)
        {
            string m_theMenu = SiteMap();

            writer.Write(m_theMenu);
        }

        public string SiteMap()
        {
            string retValue = string.Empty;

            if (AssignRoles)
            {
                retValue = ListAssignableChildNodes(System.Web.SiteMap.RootNode, true);
            }
            else
            {
                retValue = ListChildNodes(System.Web.SiteMap.RootNode, true);
            }

            return retValue;
        }

        private string ListChildNodes(System.Web.SiteMapNode node, bool root)
        {
            string image = string.Empty;

            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            if (root)
            {
                sb.Append(string.Format("<ul id=\"{0}\" class=\"{1}\">", this.ID, this.CssClass));
            }
            else
            {
                sb.Append("<ul>");
            }

            foreach (SiteMapNode item in node.ChildNodes)
            {
                if (!root)
                {
                    if (item.Url != "")
                    {
                        if (!CheckPageInRole(item)) continue;
                    }
                }

                if (item["image"] != null)
                {
                    image = string.Format("<i class=\"icon  fa {0}\"></i>", item["image"]);
                }

                string m_menuItem = string.Empty;

                if (item.Url == string.Empty)
                {
                    m_menuItem = string.Format("<li><span>{0} {1}</span>", image, item.Title);
                }
                else
                {
                    m_menuItem = string.Format("<li><a href=\"{0}\">{1} {2}</a>", item.Url, image, item.Title);
                }

                //
                sb.Append(m_menuItem);
                
                if (item.HasChildNodes)
                {
                    sb.Append(ListChildNodes(item, false));
                }

                sb.Append("</li>");
            }

            sb.Append("</ul>");

            return sb.ToString();
        }

        private bool CheckPageInRole(SiteMapNode item)
        {
            bool retValue = false;

            string m_pageName = System.IO.Path.GetFileNameWithoutExtension(item.Url); //new Uri(item.Url, UriKind.Relative).AbsolutePath);

            string[] m_roles = Roles.GetRolesForUser(CurrentUser.Identity.Name);

            ConfigurationManagerHelper m_cfgMgr = new ConfigurationManagerHelper();
            string m_applicationName = m_cfgMgr.GetApplicationName();
            string m_cn = m_cfgMgr.GetConnectionStringName();
            
            //
            Pages.ApplicationName = m_applicationName;
            Pages.ConnectionString = ConfigurationManager.ConnectionStrings[m_cn].ConnectionString;
            bool[] m_permissions = new bool[m_roles.Length];
            for (int i = 0; i < m_roles.Length; i++)
            {
                m_permissions[i] = Pages.IsPageInRole(m_pageName, m_roles[i]);
            }

            retValue = m_permissions.Contains(true);

            return retValue;
        }

        private string ListAssignableChildNodes(System.Web.SiteMapNode node, bool root)
        {
            string image = string.Empty;

            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            if (root)
            {
                sb.Append(string.Format("<ul id=\"{0}\" class=\"{1}\">", this.ID, this.CssClass));
            }
            else
            {
                sb.Append("<ul>");
            }

            foreach (SiteMapNode item in node.ChildNodes)
            {
                if (item["image"] != null)
                {
                    image = string.Format("<i class=\"icon  fa {0}\"></i>", item["image"]);
                }

                string m_menuItem = string.Empty;

                if (item.Url == string.Empty)
                {
                    m_menuItem = string.Format("<li><span>{0} {1}</span>", image, item.Title);
                }
                else
                {
                    m_menuItem = string.Format("<li><a href=\"javascript:AssignRole('{0}', '{1}')\">{2} {3}</a>", item.Title, item["id"], image, item.Title);
                }


                sb.Append(m_menuItem);

                if (item.HasChildNodes)
                {
                    sb.Append(ListAssignableChildNodes(item, false));
                }

                sb.Append("</li>");
            }

            sb.Append("</ul>");

            return sb.ToString();
        }

        private string GetSiteMapLevelAsBulletedListForAssignRoles(SiteMapNodeCollection nodes)
        {
            string output = String.Empty;

            foreach (SiteMapNode node in nodes)
            {
                bool m_masterRoot = (node.Title == "MasterRoot");

                string image = string.Empty;
                if (node["image"] != null)
                {
                    image = string.Format("<span class=\"fa {0}\"></span> ", node["image"]);
                }

                if (node.HasChildNodes)
                {
                    if (!m_masterRoot)
                    {
                        output += String.Format("<li id=\"0\" class=\"xn-openable\">\n<a href=\"javascript:AssignRole('{2}', '{0}')\">{1}<span class=\"xn-text\">{2}</span></a>\n", node["id"], image, node.Title);
                    }
                }
                else
                {
                    output += String.Format("<li id=\"{0}\">\n<a href=\"javascript:AssignRole('{2}', '{0}')\">{1}{2}</a>\n", node["id"], image, node.Title);
                }


                //Add any children levels, if needed (recursively)
                if (node.HasChildNodes)
                {
                    if ((node["includeRoot"] != null) && (!bool.Parse(node["includeRoot"])))
                    {
                        output += String.Format("{0}\n", GetSiteMapLevelAsBulletedListForAssignRoles(node.ChildNodes));
                    }
                    else
                    {
                        output += String.Format("<ul id=\"{0}\">{1}</ul>\n", node.Title, GetSiteMapLevelAsBulletedListForAssignRoles(node.ChildNodes));
                    }
                }

                if (!m_masterRoot)
                {
                    output += "</li>\n";
                }
            }

            return output;
        }
    }
}
